package com.pzhu.service.Impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pzhu.mapper.*;
import com.pzhu.model.dto.OrderDto;
import com.pzhu.model.dto.OrderParamDto;
import com.pzhu.model.entity.*;
import com.pzhu.model.help.QRInfo;
import com.pzhu.model.help.ResponseResult;
import com.pzhu.model.vo.OrderUndeliveredVo;
import com.pzhu.model.vo.OrderVo;
import com.pzhu.service.OrderService;
import com.pzhu.utils.BeanCopyUtils;
import com.pzhu.utils.ToolUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author Administrator
 * @description 针对表【hs_order(订单表)】的数据库操作Service实现
 * @createDate 2023-12-21 20:27:36
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order>
        implements OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private StaffMapper staffMapper;
    @Autowired
    private BookableMapper bookableMapper;
    @Autowired
    private ThaliMapper thaliMapper;
    @Autowired
    private WageMapper wageMapper;
    @Autowired
    private ThaliCareerMapper thaliCareerMapper;
    @Autowired
    private VipMapper vipMapper;
    @Autowired
    private SpecsMapper specsMapper;
    @Autowired
    private QRService qrService;

    @Override
    @Transactional
    public ResponseResult pay(OrderDto orderDto) {

        //减去价格
        BigDecimal totalAmount = orderDto.getTotalAmount();
        Vip vip = vipMapper.selectOne(new LambdaQueryWrapper<Vip>()
                .eq(Vip::getUserId, orderDto.getCustomerId()));

        if (vip.getPrice().compareTo(totalAmount) < 0) {
            return ResponseResult.error("余额不足请充值！");
        }
        vip.setPrice(vip.getPrice().subtract(totalAmount));
        vipMapper.updateById(vip);


        Order order = BeanCopyUtils.copyBean(orderDto, Order.class);
        //订单号
        order.setCode(ToolUtils.getCode());

        //生成核销码
        QRInfo qrInfo = BeanCopyUtils.copyBean(order, QRInfo.class);

        //找出该规格的优惠和数量
        Specs specs = specsMapper.selectOne(
                new LambdaQueryWrapper<Specs>()
                        .eq(Specs::getId, orderDto.getSpecsId()));
        qrInfo.setRate(specs.getRate());
        qrInfo.setCount(specs.getCount());
        String jsonString = JSON.toJSONString(qrInfo);
        long timestamp = System.currentTimeMillis();
        qrService.generateFile(jsonString, new File("D:\\My\\毕设资料\\household-img\\qr_code\\" + timestamp + ".png"));
        order.setCodeUrl(timestamp + ".png");


        Long staffId = orderDto.getStaffId();
        Integer area = orderDto.getArea();
        Long bookableId = orderDto.getBookableId();

        //选择保洁阿姨、有选择预约时间
        if (ObjectUtil.isNotNull(staffId) && ObjectUtil.isNotNull(area) && ObjectUtil.isNotNull(bookableId)) {
            Bookable bookable = bookableMapper.selectById(orderDto.getBookableId());
            bookable.setIsOrder(false);
            bookableMapper.updateById(bookable);
            order.setStartTime(bookable.getStartTime());
            order.setEndTime(bookable.getEndTime());
            order.setStatus(1);
        }

        //保洁 没选阿姨 根据面积大小来计算大概时间，通过选择的开始时间来进行匹配
        if (ObjectUtil.isNull(staffId) && ObjectUtil.isNotNull(area) && ObjectUtil.isNull(bookableId)) {
            //没选保洁阿姨直接自动查找是否有满足的 根据时间计算
            //找出该类别属于哪个工种阿姨管
            Thali thali = thaliMapper.selectOne(new LambdaQueryWrapper<Thali>().eq(Thali::getId, order.getThaliId()));


            //找出所有阿姨
            List<Staff> staffInfoList = staffMapper.selectList(new LambdaQueryWrapper<Staff>().eq(Staff::getCareerId,
                    thaliCareerMapper.selectOne(new LambdaQueryWrapper<ThaliCareer>().eq(ThaliCareer::getThaliId, thali.getId()))
                            .getCareerId()));

            //设置开始时间和结束时间
            Date endTime = new Date(order.getStartTime().getTime() +
                    Double.valueOf((orderDto.getArea() / 25.0) * 3600000).longValue());

            Date startTime = order.getStartTime();

            //找出匹配阿姨最接近时间
            staffInfoList.forEach(v -> {
                LambdaQueryWrapper<Bookable> bookableQueryWrapper = new LambdaQueryWrapper<>();
                bookableQueryWrapper.eq(Bookable::getStaffId, v.getId())
                        .eq(Bookable::getIsOrder, false);
                List<Bookable> bookableList = bookableMapper.selectList(bookableQueryWrapper);
                bookableList.forEach(t -> {
                    //判断时间在区间里面直接预约
                    // TODO 误差区间设置是否
                    if (betweenOn(startTime, endTime, t.getStartTime(), t.getEndTime())) {
                        order.setStartTime(t.getStartTime());
                        order.setEndTime(t.getEndTime());
                        order.setStaffId(v.getId());
                        order.setStaffName(v.getUsername());
                        //设置当前预约时间被预约了
                        t.setIsOrder(true);
                        bookableMapper.updateById(t);
                    } else {
                        order.setEndTime(endTime);
                    }
                });
            });
        }

        //选择阿姨 非保洁  只需要选择一个到达时间即可（判断面积为空 阿姨ID不为空）
        if (ObjectUtil.isNotNull(staffId) && ObjectUtil.isNull(area)) {
            order.setStatus(1);
        }

        //没选择阿姨 筛选此时有空的阿姨 进行匹配
        if (ObjectUtil.isNull(staffId) && ObjectUtil.isNull(area)) {
            Thali thali = thaliMapper.selectOne(
                    new LambdaQueryWrapper<Thali>()
                            .eq(Thali::getId, orderDto.getThaliId()));

            List<Staff> staffInfoList = staffMapper
                    .selectList(new LambdaQueryWrapper<Staff>()
                            .eq(Staff::getCareerId, thaliCareerMapper.selectOne(new LambdaQueryWrapper<ThaliCareer>().eq(ThaliCareer::getThaliId, thali.getId())).getCareerId())
                            .eq(Staff::getStatus, true));

            if (staffInfoList.size() > 0) {
                Random random = new Random();
                int randomNumber = random.nextInt(staffInfoList.size());

                Staff staff = staffInfoList.get(randomNumber);

                staff.setStatus(false);
                staffMapper.updateById(staff);
                order.setStaffId(staff.getId());
                order.setStaffName(staff.getUsername());
                order.setStatus(1);
            }
        }

        order.setCreateTime(new Date());
        orderMapper.insert(order);

        return ResponseResult.ok();
    }

    @Override
    public ResponseResult getOrder(Integer status) {
        //首先判断时间是否过期，过期修改状态
        Order order = new Order();
        order.setStatus(3);
        orderMapper.update(order, new LambdaQueryWrapper<Order>()
                .and(x -> x.eq(Order::getStatus, 1)
                        .or()
                        .eq(Order::getStatus, 0))
                .lt(Order::getEndTime, new Date()));

        //查询
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(status != -1, Order::getStatus, status)
                .orderByAsc(Order::getStatus);
        List<Order> orderList = orderMapper.selectList(queryWrapper);

        List<OrderVo> orderVoList = BeanCopyUtils.copyBeanList(orderList, OrderVo.class);


        Map<String, Object> map = new HashMap<>();
        map.put("list", orderVoList);
        return ResponseResult.ok(map);
    }

    @Override
    public ResponseResult undelivered(OrderParamDto orderParamDto) {
        //查出阿姨所属类别
        LambdaQueryWrapper<Staff> staffQueryWrapper = new LambdaQueryWrapper<>();
        staffQueryWrapper.eq(Staff::getId, orderParamDto.getStaffId());
        Staff staff = staffMapper.selectOne(staffQueryWrapper);

        System.err.println("阿姨信息" + staff);

        //根据类别查找类型
        LambdaQueryWrapper<Thali> thaliQueryWrapper = new LambdaQueryWrapper<>();

        Long[] thaliIds = thaliCareerMapper.selectList(new LambdaQueryWrapper<ThaliCareer>().eq(ThaliCareer::getCareerId, staff.getCareerId())).stream().map(ThaliCareer::getThaliId)
                .toArray(Long[]::new);

        thaliQueryWrapper.in(Thali::getId, thaliIds);
        List<Thali> thaliList = thaliMapper.selectList(thaliQueryWrapper);

        for (Thali thali : thaliList) {
            System.err.println(thali.getName());
        }

        List<Order> orderList = new ArrayList<>();

        System.err.println(ObjectUtil.isNotNull(orderParamDto.getStartTime()));


        //对所有订单进行判断是否过期
        Order order = new Order();
        order.setStatus(3);
        orderMapper.update(order, new LambdaQueryWrapper<Order>()
                .and(x -> x.eq(Order::getStatus, 1)
                        .or()
                        .eq(Order::getStatus, 0))
                .lt(Order::getEndTime, new Date()));

        //类型查找所有的订单信息  条件筛选
        thaliList.forEach(v -> {
            LambdaQueryWrapper<Order> orderQueryWrapper = new LambdaQueryWrapper<>();
            orderQueryWrapper.eq(Order::getThaliId, v.getId())
                    .isNull(Order::getStaffId)
                    .eq(Order::getStatus, 1)
                    .apply(ObjectUtil.isNotNull(orderParamDto.getToday()), "DATE_FORMAT (start_time,'%Y-%m-%d') = DATE_FORMAT(NOW(),'%Y-%m-%d')")
                    .apply(ObjectUtil.isNotNull(orderParamDto.getTomorrow()), "DATE_FORMAT (start_time,'%Y-%m-%d') = DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 DAY),'%Y-%m-%d')")
                    .apply(ObjectUtil.isNotNull(orderParamDto.getStartTime()), "DATE_FORMAT (start_time,'%Y-%m-%d') >= DATE_FORMAT({0},'%Y-%m-%d')", orderParamDto.getStartTime())
                    .apply(ObjectUtil.isNotNull(orderParamDto.getEndTime()), "DATE_FORMAT (start_time,'%Y-%m-%d') <= DATE_FORMAT({0},'%Y-%m-%d')", orderParamDto.getEndTime())
                    .like(StrUtil.isNotBlank(orderParamDto.getAddress()), Order::getAddress, orderParamDto.getAddress())
                    .orderByAsc(Order::getStartTime);
            List<Order> orders = orderMapper.selectList(orderQueryWrapper);
            orderList.addAll(orders);
        });


        List<OrderUndeliveredVo> orderUndeliveredVoList =
                BeanCopyUtils.copyBeanList(orderList, OrderUndeliveredVo.class);

        Map<String, Object> map = new HashMap<>();
        map.put("list", orderUndeliveredVoList);

        return ResponseResult.ok(map);
    }


    /**
     * 算是否在时间段内
     *
     * @param date1 小区间开始时间
     * @param date2 小区间结束时间
     * @param date3 大区间开始时间
     * @param date4 大区间结束时间
     * @return
     */
    public static boolean betweenOn(Date date1, Date date2, Date date3, Date date4) {
        if (date1 == null || date2 == null || date3 == null || date4 == null) {
            return false;
        }
        return (date1.getTime() - date3.getTime()) >= 0 && ((date4.getTime() - date2.getTime()) >= 0);
    }
}




